/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.metadata.rtcustomization.common;

import com.inspur.edp.metadata.rtcustomization.api.entity.GspEmbeddedMdRtContent;
import com.inspur.edp.metadata.rtcustomization.api.entity.SourceTypeEnum;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.data.multilang.CAFMultiLanguageColumn;
import io.iec.edp.caf.i18n.api.LanguageService;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class PredicateUtils {
    private static LanguageService languageService = SpringBeanUtils.getBean(LanguageService.class);
    private static final String defaultI18nAttributeName = "cafMlcchs";
    private static final String FIELD_CODE = "code";
    private static final String FIELD_NAME = "name";
    private static final String FIELD_TYPE = "type";
    private static final String FIELD_NAMESPACE = "nameSpace";
    private static final String FIELD_SOURCETYPE = "sourceType";
    private static final String FIELD_BIZOBJID = "bizObjId";

    /**
     * 构建元数据查询条件
     *
     * @param keyword
     * @param metadataTypes
     * @param cb
     * @param root
     * @return
     */
    public static Predicate buildMdQueryPredicate(String keyword, String bizobjectID, List<String> metadataTypes, SourceTypeEnum sourceType, CriteriaBuilder cb, Root root, Class entityClass) {
        List<Predicate> predicates = new ArrayList<>();

        // 元数据类型过滤
        if (!CollectionUtils.isEmpty(metadataTypes)) {
            List<String> typeList = metadataTypes.stream().map(String::toLowerCase).collect(Collectors.toList());
            Predicate typePredicate = cb.lower(root.get(FIELD_TYPE)).in(typeList);
            predicates.add(typePredicate);
        }
        String fieldSuffix = languageService.getFieldSuffix().toLowerCase().substring(1);
        String currentI18nAttributeName = CAFMultiLanguageColumn.fieldPrefix + fieldSuffix;
        // 关键字过滤 模糊匹配 元数据的code name namespace
        if (StringUtils.hasText(keyword)) {
            keyword = keyword.toLowerCase();
            Predicate conditionPredicate = null;
            // 构造多语言名称表达式
            Expression<String> nameExpression = null;
            if(entityClass == GspEmbeddedMdRtContent.class){
                // 如果当前语言对应的名称为空，则取默认语言的名称
                 nameExpression = cb.coalesce(
                        cb.lower(root.get(FIELD_NAME).get(currentI18nAttributeName)),
                        cb.lower(root.get(FIELD_NAME).get(defaultI18nAttributeName)));
            } else {
                nameExpression = cb.lower(root.get(FIELD_NAME));
            }

            conditionPredicate = cb.or(cb.like(cb.lower(root.get(FIELD_CODE)), "%" + keyword + "%")
                    , cb.like(nameExpression, "%" + keyword + "%")
                    , cb.like(cb.lower(root.get(FIELD_NAMESPACE)), "%" + keyword + "%"));
            // 应用查询条件
            predicates.add(conditionPredicate);
        }
        // 源类型过滤
        if (Objects.nonNull(sourceType)) {
            Predicate sourceTypePredicate = cb.equal(root.get(FIELD_SOURCETYPE), sourceType.getCode());
            predicates.add(sourceTypePredicate);
        }
        // 排除当前业务对象下的数据库元数据
        if (StringUtils.hasText(bizobjectID)) {
            Predicate bizObjIdPredicate = cb.or(cb.isNull(root.get(FIELD_BIZOBJID)), cb.notEqual(root.get(FIELD_BIZOBJID), bizobjectID));
            predicates.add(bizObjIdPredicate);
        }
        Predicate finalPredicate = cb.and(predicates.toArray(new Predicate[0]));

        return finalPredicate;
    }
}
